<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace buwang\util;

use think\facade\Cache;
use buwang\traits\JwtTrait;
use app\manage\model\Member;
use app\common\model\MemberMiniapp;
use app\common\model\Miniapp;
use dh2y\qrcode\QRcode;
use upload\Uploadfile;
use think\file\UploadedFile;
use buwang\facade\WechatProgram;
use app\manage\model\Token;

//微信公众号
class Util
{
    use JwtTrait;

    /**
     * 字符串命名风格转换
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
     * @access public
     * @param string $name 字符串
     * @param integer $type 转换类型
     * @param bool $ucfirst 首字母是否大写（驼峰规则）
     * @return string
     */
    public static function parseName($name, $type = 0, $ucfirst = true)
    {
        if ($type) {
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $name);
            return $ucfirst ? ucfirst($name) : lcfirst($name);
        }

        return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
    }

    /**
     * 清除模版缓存 不删除cache目录
     */
    public static function clear_sys_cache()
    {
        Cache::clear();
        return true;
    }

    public static function toreplace($str, $find)//$str是你需要操作的字符串,$find是你指定的字符串
    {
        if (strpos($str, $find) === false) return false;

        $a = explode($find, $str);
        return $a[0] . $find;
    }


    /**
     * 无限级归类
     *
     * @param array $list 归类的数组
     * @param string $id 父级ID
     * @param string $pid 父级PID
     * @param string $child key
     * @param string $root 顶级
     *
     * @return array
     */
    public static function tree(array $list, string $pk = 'id', string $pid = 'pid', string $child = 'child', int $root = 0): array
    {
        $tree = [];  //最终得到的树形数据

        if (is_array($list)) {
            $refer = [];

            //基于数组的指针(引用) 并 同步改变数组
            foreach ($list as $key => $val) {
                $list[$key][$child] = [];
                $refer[$val[$pk]] = &$list[$key];  //以主键为下标，值为列表数据的引用
            }


            foreach ($list as $key => $val) {
                //是否存在parent
                $parentId = isset($val[$pid]) ? $val[$pid] : $root;  //取出父级id

                //如果是根节点，直接放入根层级(实际放入的是一个组装好的树分支)
                if ($root == $parentId) {
                    $tree[$val[$pk]] = &$list[$key];
                } else {  //如果是其他节点，通过引用传入树分支


                    if (isset($refer[$parentId])) {

                        $refer[$parentId][$child][] = &$list[$key];  //1  3  4

                    }
                }

            }
            // die;
        }
        //var_dump(array_values($tree));
        return array_values($tree);
    }


    /**得到关系树中的全部用户id（递归）
     * @param array $list tree数据来源
     * @param string $name 需要获取的数据名
     * @param string $child 树子节点名
     * @return array
     */
    public static function getTreeItem(array $list, string $name = 'pid', string $child = 'child')
    {
        $item = [];
        //遍历关系
        foreach ($list as &$value) {
            $item[] = $value[$name];
            if ($value[$child]) $item = array_merge($item, self::getTreeItem($value[$child], $name, $child));//合并两个数组
        }
        return $item;
    }


    /**
     * 排列组合
     *
     * @param array $input 排列的数组
     *
     * @return array
     */
    static public function arrayArrange(array $input): array
    {
        $temp = [];
        $result = array_shift($input);  //挤出数组第一个元素
        $i = 0;
        while ($item = array_shift($input))  //循环每次挤出数组的一个元素，直到数组元素全部挤出
        {
            $temp = $result;
            $result = [];
            //var_dump('temp',$temp);
            foreach ($temp as $v) {
                foreach ($item as $val) {
                    //var_dump('排列组合',array_merge_recursive($v, $val));
                    $result[] = array_merge_recursive($v, $val);

                }
            }
            //var_dump('第'.++$i.'页',$result);
        }
        //die;
        return $result;
    }

    /**
     * 富文本base64解码
     */
    public static function r_text_decode($text)
    {
        $text = base64_decode($text);
        //var_dump($r_textarea);die;
        return htmlspecialchars_decode(urldecode($text));
    }


    /**取$member_id 不传如果是租户或者用户则自动查询$member_id
     * @return array|mixed
     */
    public static function getLoginMemberId($member_id = null, $dir = null)
    {
        $jwtinfo = null;
        $scopes = '';
        $service_id = null;
        $member_miniapp = null;
        $request = app("app\Request");//得到注入的request单例
        $token = get_token($request);//得到token
        try {
            if ($token) $jwtinfo = self::decodeToken($token);//解析token,获取用户信息
        } catch (\Throwable $e) {
            $jwtinfo = null;
            $token = null;
        }
        //TODO: 2021/4/29 getLoginMemberId 方法增加服务器登录鉴权
        if ($jwtinfo && $token) {
            //应用类型 mini_program app h5 official pc
            $scopes = $jwtinfo->scopes;
            //redis验证,如果验证未通过则也按照未登录的情况处理
            $user = Token::validateRedisToken($token, $jwtinfo);
            if (!$user) {
                $jwtinfo = null;
                $token = null;
            }
        }

        //根据登录情况判断取配置值的权限
        $memberId = $member_id;
        $Dir = $dir;
        $header = $request->header();
        if (isset($header['request-app'])) $service_id = $header['request-app'];
        if ($jwtinfo) {
            $scopes = $jwtinfo->scopes;
            //租户登录 取顶级租户配置
            if ($jwtinfo->scopes == 'member' && !$member_id) {
                $topuser = Member::getTop($jwtinfo->data->id);
                if ($topuser && isset($topuser['id'])) $memberId = $topuser['id'];
            }
            //admin登录但传了$member_id，则也查租户配置
            if ($jwtinfo->scopes == 'admin' && $member_id) {
                $topuser = Member::getTop($member_id);
                if ($topuser && isset($topuser['id'])) $memberId = $topuser['id'];
            }
        } elseif ($member_id) {
            //如果没登录但是传了$member_id，则也可查租户配置
            $topuser = Member::getTop($member_id);
            if ($topuser && isset($topuser['id'])) $memberId = $topuser['id'];
        }

        if ($service_id) {
            //获取服务实例
            $MemberMiniapp = MemberMiniapp::where('service_id', $service_id)->find();
            if ($MemberMiniapp && isset($MemberMiniapp['member_id'])) {
                $member_miniapp = $MemberMiniapp;
                if (!$member_id) {
                    //查询顶级租户
                    $topuser = Member::getTop($MemberMiniapp['member_id']);
                    if ($topuser && isset($topuser['id'])) $memberId = $topuser['id'];
                }
                //加入应用配置赛选
                if (!$Dir) {
                    //得到应用的dirId
                    $miniapp = Miniapp::find($MemberMiniapp['miniapp_id']);
                    if ($miniapp && isset($miniapp['dir'])) $Dir = $miniapp['dir'];
                }
            }
        }
        if (!$Dir) {
            $Dir = app('http')->getName();
        }

        //不是租户登录也没传租户id则返回默认值
        // if(!$memberId)return $default;

        return ['memberId' => $memberId, 'scopes' => $scopes, 'dir' => $Dir, 'jwtinfo' => $jwtinfo, 'member_miniapp' => $member_miniapp];
    }


    /**
     * 获取二维码
     * @param $url
     * @param $name
     * @return array|bool|string
     * @noinspection DuplicatedCode
     */
    public static function getQRCodePath($url, $name, $member_mini_app = [])
    {
        try {
            if (!strlen(trim($url)) || !strlen(trim($name))) {
                exception('getQRCodePath传参错误！');
            }
            if ($member_mini_app && (!isset($member_mini_app['id']) || !isset($member_mini_app['member_id']))) {
                exception('getQRCodePath传参错误！');
            }
            $upload = [];
            $outfile = config('qrcode.cache_dir');  //本地缓存地址
            $code = new QRcode();
            $wapCodePath = $code->png($url, $outfile . '/' . $name)->getPath(); //获取二维码生成的地址
            //得到二维码的文件流
            $content = file_get_contents('.' . $wapCodePath);
            $files = new UploadedFile('.' . $wapCodePath, $name, 'image/jpeg');

            $uploadConfig = bw_config('base');//得到所有基础配置
            $default = \app\common\model\Config::getConfigData('storage', 'default', 'local');
            $uploadConfig['upload_type'] = $default ?? $uploadConfig['upload_type'];

            $uploadConfig['upload_allow_type'] = "local,alioss,qnoss,txcos";
            //得到第三方服务器上传相关配置
            if ($uploadConfig['upload_type'] !== 'local') {
                $uploadConfig = array_merge($uploadConfig, \app\common\model\Config::getConfigData('storage', $uploadConfig['upload_type'], 'local'));
            }
            $upload = Uploadfile::instance()
                ->setUploadType($uploadConfig['upload_type'])
                ->setUploadConfig($uploadConfig)
                ->setMemberId($member_mini_app['member_id'] ?? 0)
                ->setFile($files)
                ->save();
            // TODO: 生成后删除源文件
            @unlink('.' . $wapCodePath);
            if ($upload['save']) {
                return $upload['file_info'];
            } else {
                return $upload['msg'];
            }
        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }


    /**
     * TODO 砍价 拼团 分享海报生成
     * @param array $data
     * @param $path
     * @param $fileName
     * @return array|bool|string
     * @throws \Exception
     */
    public static function setShareMarketingPoster($data = [], $path = '', $fileName = '')
    {
        if (!@fopen($data['image'], 'r')) throw new \Exception('缺少商品图片');
        if (!@fopen($data['url'], 'r')) throw new \Exception('缺少二维码图片');
        $config = array(
            'text' => array(
                array(
                    'text' => $data['price'],//TODO 价格
                    'left' => 116,
                    'top' => 200,
                    'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                    'fontSize' => 50,             //字号
                    'fontColor' => '255,0,0',       //字体颜色
                    'angle' => 0,
                ),
                array(
                    'text' => $data['label'],//TODO 标签
                    'left' => 450,
                    'top' => 188,
                    'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                    'fontSize' => 24,             //字号
                    'fontColor' => '255,255,255',       //字体颜色
                    'angle' => 0,
                ),
                array(
                    'text' => $data['msg'],//TODO 简述
                    'left' => 80,
                    'top' => 270,
                    'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                    'fontSize' => 22,             //字号
                    'fontColor' => '40,40,40',       //字体颜色
                    'angle' => 0,
                )
            ),
            'image' => array(
                array(
                    'url' => $data['image'],     //图片
                    'stream' => 0,
                    'left' => 120,
                    'top' => 340,
                    'right' => 0,
                    'bottom' => 0,
                    'width' => 450,
                    'height' => 450,
                    'opacity' => 100
                ),
                array(
                    'url' => $data['url'],     //二维码资源
                    'stream' => 0,
                    'left' => 260,
                    'top' => 890,
                    'right' => 0,
                    'bottom' => 0,
                    'width' => 160,
                    'height' => 160,
                    'opacity' => 100
                )
            ),
            'background' => 'static/bwmall/poster/poster.jpg'
        );
        if (!file_exists($config['background'])) throw new \Exception('缺少系统预设背景图片');
        if (strlen($data['title']) < 36) {
            $text = array(
                'text' => $data['title'],//TODO 标题
                'left' => 76,
                'top' => 100,
                'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                'fontSize' => 32,         //字号
                'fontColor' => '0,0,0',       //字体颜色
                'angle' => 0,
            );
            array_push($config['text'], $text);
        } else {
            $titleOne = array(
                'text' => mb_strimwidth($data['title'], 0, 24),//TODO 标题
                'left' => 76,
                'top' => 70,
                'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                'fontSize' => 32,         //字号
                'fontColor' => '0,0,0',       //字体颜色
                'angle' => 0,
            );
            $titleTwo = array(
                'text' => mb_strimwidth($data['title'], mb_strlen(mb_strimwidth($data['title'], 0, 24)), 24),//TODO 标题
                'left' => 76,
                'top' => 120,
                'fontPath' => app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf',     //字体文件
                'fontSize' => 32,         //字号
                'fontColor' => '0,0,0',       //字体颜色
                'angle' => 0,
            );
            array_push($config['text'], $titleOne);
            array_push($config['text'], $titleTwo);
        }
        return self::setSharePoster($config, $path, $fileName);
    }


    /**
     * TODO 优惠券分享海报生成
     * @param array $data 参数
     * @param $path  生成路径
     * @param $fileName  生成文件名
     * @return array|bool|string
     * @throws \Exception
     */
    public static function setShareCouponPoster($data = [], $path = '', $fileName = '')
    {
        $beijing_url = $data['background_image'];//海报最底层得背景
        $logourl = $data['avatar'];//微信头像
        $erweimaurl = $data['url'];//二维码
        $nickname = $data['nickname'];//用户名
        $price = $data['price'];    //用户名
//imagecreate系列函数用于从文件或 URL 载入一幅图像，成功返回图像资源，失败则返回一个空字符串。
        list($pic_w, $pic_h, $pic_type) = getimagesize($beijing_url);
        $beijing = imagecreatefromstring(file_get_contents($beijing_url));//从文件或 URL 名中载入一幅png图像
        $logourl = self::scaleImg($logourl, self::yuan_img($logourl), 50, 50);//从文件或 URL 名中载入一幅png图像
        $erweimaurl = self::scaleImg($erweimaurl, imagecreatefromstring(file_get_contents($erweimaurl)), 160, 160); //从文件或 URL 名中载入一幅png图像

//建立的是一幅大小为 x和 y的黑色图像(默认为黑色)
        $image_3 = imageCreatetruecolor(imagesx($beijing), imagesy($beijing));//获取图像宽度函数：imagesx() 获取图像高度函数：imagesy()
        $color = imagecolorallocate($image_3, 255, 255, 255);//imagecolorallocate:为一幅图像分配颜色，它的返回值将作为填充颜色函数imagefill($img,0,0,$color)的$color参数
        imagefill($image_3, 0, 0, $color);//imagefill:改变一幅图像的背景颜色
        $middle_point = $pic_w / 2; //背景中间点
        imagecopyresampled($image_3, $beijing, 0, 0, 0, 0, imagesx($beijing), imagesy($beijing), imagesx($beijing), imagesy($beijing));
        $rqys = imagecolorallocate($image_3, 0, 0, 0);//获取一个传参用的颜色
        $red = imagecolorallocate($image_3, 234, 42, 21);//获取一个传参用的颜色
        $font = app()->getRootPath() . 'public/static/font/Alibaba-PuHuiTi-Regular.otf';  //写的文字用到的字体。字体最好用系统有得，否则会包charmap的错，这是黑
//字体中间点
        $sub = (strlen($nickname) * 8) / 2;
        imagettftext($image_3, 16, 0, $middle_point - $sub, 350, $rqys, $font, $nickname);
//字体中间点
        $sub = (strlen($price) * 40) / 2;
        imagettftext($image_3, 80, 0, $middle_point - $sub, 540, $red, $font, $price);
//图片中间点
        $sub = imagesx($logourl) / 2;
//插入图片
        imagecopymerge($image_3, $logourl, $middle_point - $sub, 270, 0, 0, imagesx($logourl), imagesy($logourl), 100);//目标图,源图，上，右，下，宽度，高度，透明度
//图片中间点
        $sub = imagesx($erweimaurl) / 2;
//插入图片
        imagecopymerge($image_3, $erweimaurl, $middle_point - $sub - 5, 685, 0, 0, imagesx($erweimaurl), imagesy($erweimaurl), 100);//目标图,源图，上，右，下，宽度，高度，透明度

        ob_start();
        imagejpeg($image_3);
        imagedestroy($image_3);
        $res = ob_get_contents();//文件二进制流
        ob_end_clean();
        try {
            $uploadConfig = bw_config('base');//得到所有基础配置
            $default = \app\common\model\Config::getConfigData('storage', 'default', 'local');
            $uploadConfig['upload_type'] = $default ?? $uploadConfig['upload_type'];

            $uploadConfig['upload_allow_type'] = "local,alioss,qnoss,txcos";
            //得到第三方服务器上传相关配置
            if ($uploadConfig['upload_type'] !== 'local') {
                $uploadConfig = array_merge($uploadConfig, \app\common\model\Config::getConfigData('storage', $uploadConfig['upload_type'], 'local'));
            }
            $outfile = config('qrcode.cache_dir');  //本地缓存地址
            if (!file_exists('./' . $outfile . $path)) mkdir('./' . $outfile . $path, 0777, true);
            $filepath = './' . $outfile . $path . '/' . $fileName;
            file_put_contents($filepath, $res);
            $files = new UploadedFile($filepath, $fileName, 'image/jpeg');
            $upload = Uploadfile::instance()
                ->setUploadType($uploadConfig['upload_type'])
                ->setUploadConfig($uploadConfig)
                ->setFile($files)
                ->save();
            if ($upload['save'] == true) {
                return $upload['file_info'];
            } else {
                return $upload['msg'];
            }

        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }


    /**
     * TODO 生成分享二维码图片
     * @param array $config
     * @param $path
     * @param $fileName
     * @return array|bool|string
     */
    public static function setSharePoster($config = [], $path = '', $fileName = '')
    {
        //默认嵌入的图片配置
        $imageDefault = array(
            'left' => 0,
            'top' => 0,
            'right' => 0,
            'bottom' => 0,
            'width' => 100,
            'height' => 100,
            'opacity' => 100
        );
        //默认嵌入的文字配置
        $textDefault = array(
            'text' => '',
            'left' => 0,
            'top' => 0,
            'fontSize' => 32,       //字号
            'fontColor' => '255,255,255', //字体颜色
            'angle' => 0,
        );
        $background = $config['background'];//海报最底层得背景
        if (substr($background, 0, 1) === '/') {
            $background = substr($background, 1);
        }
        $backgroundInfo = getimagesize($background);
        $background = imagecreatefromstring(file_get_contents($background));
        $backgroundWidth = $backgroundInfo[0];  //背景宽度
        $backgroundHeight = $backgroundInfo[1];  //背景高度
        $imageRes = imageCreatetruecolor($backgroundWidth, $backgroundHeight);
        $color = imagecolorallocate($imageRes, 0, 0, 0);
        imagefill($imageRes, 0, 0, $color);
        imagecopyresampled($imageRes, $background, 0, 0, 0, 0, imagesx($background), imagesy($background), imagesx($background), imagesy($background));
        if (!empty($config['image'])) {
            foreach ($config['image'] as $key => $val) {
                $val = array_merge($imageDefault, $val);
                $info = getimagesize($val['url']);
                $function = 'imagecreatefrom' . image_type_to_extension($info[2], false);
                if ($val['stream']) {
                    $info = getimagesizefromstring($val['url']);
                    $function = 'imagecreatefromstring';
                }
                $res = $function($val['url']);
                $resWidth = $info[0];
                $resHeight = $info[1];
                $canvas = imagecreatetruecolor($val['width'], $val['height']);
                imagefill($canvas, 0, 0, $color);
                imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'], $resWidth, $resHeight);
                $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) - $val['width'] : $val['left'];
                $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) - $val['height'] : $val['top'];
                imagecopymerge($imageRes, $canvas, $val['left'], $val['top'], $val['right'], $val['bottom'], $val['width'], $val['height'], $val['opacity']);//左，上，右，下，宽度，高度，透明度
            }
        }
        if (isset($config['text']) && !empty($config['text'])) {
            foreach ($config['text'] as $key => $val) {
                $val = array_merge($textDefault, $val);
                list($R, $G, $B) = explode(',', $val['fontColor']);
                $fontColor = imagecolorallocate($imageRes, $R, $G, $B);
                $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) : $val['left'];
                $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) : $val['top'];
                imagettftext($imageRes, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
            }
        }
        ob_start();
        imagejpeg($imageRes);
        imagedestroy($imageRes);
        $res = ob_get_contents();//文件二进制流
        ob_end_clean();
        try {
            $uploadConfig = bw_config('base');//得到所有基础配置
            $default = \app\common\model\Config::getConfigData('storage', 'default', 'local');
            $uploadConfig['upload_type'] = $default ?? $uploadConfig['upload_type'];

            $uploadConfig['upload_allow_type'] = "local,alioss,qnoss,txcos";
            //得到第三方服务器上传相关配置
            if ($uploadConfig['upload_type'] !== 'local') {
                $uploadConfig = array_merge($uploadConfig, \app\common\model\Config::getConfigData('storage', $uploadConfig['upload_type'], 'local'));
            }
            $outfile = config('qrcode.cache_dir');  //本地缓存地址
            if (!file_exists('./' . $outfile . $path)) mkdir('./' . $outfile . $path, 0777, true);
            $filepath = './' . $outfile . $path . '/' . $fileName;
            file_put_contents($filepath, $res);
            $files = new UploadedFile($filepath, $fileName, 'image/jpeg');
            $upload = Uploadfile::instance()
                ->setUploadType($uploadConfig['upload_type'])
                ->setUploadConfig($uploadConfig)
                ->setFile($files)
                ->save();
            // TODO: 生成后删除源文件
            @unlink($filepath);
            if ($upload['save'] == true) {
                return $upload['file_info'];
            } else {
                return $upload['msg'];
            }

        } catch (\Exception $e) {
            return $e->getMessage();
        }
    }


    /**
     * 获取小程序二维码
     * @param string $url
     * @param array $param
     * @param string $name
     * @param $member_mini_app
     * @return array|bool|string
     */
    public static function getMiniQRCodePath(string $url, array $param, string $name, $member_mini_app = [])
    {
        if (!strlen(trim($url)) || !strlen(trim($name))) return false;
        try {
            $upload = [];
            $outfile = config('qrcode.cache_dir') . '/';  //本地缓存地址
            if (!isset($member_mini_app['id']) || !isset($member_mini_app['member_id'])) {
                return 'getMiniQRCodePath传参错误！';
            }
            //生成小程序二维码
            $app = WechatProgram::getWechatObj($member_mini_app['id']);
            if (!$app) return '微信认证失败,请确认应用已授权!';
            $response = $app->app_code->getUnlimit(http_build_query($param), [
                'page' => $url,
                'width' => 280,
            ]);
            //正确返回
            if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                //保存临时地址
                $filename = $response->saveAs($outfile, 'appcode.png');

                $wapCodePath = '/' . str_replace('\\', '/', $outfile . $filename);
            } else {
                //错误返回
                return '生成小程序码错误';
            }

            //保存到第三方文件
            $files = new UploadedFile('.' . $wapCodePath, $name, 'image/jpeg');
            $uploadConfig = bw_config('base');//得到所有基础配置

            $default = \app\common\model\Config::getConfigData('storage', 'default', 'local');
            $uploadConfig['upload_type'] = $default ?? $uploadConfig['upload_type'];

            $uploadConfig['upload_allow_type'] = "local,alioss,qnoss,txcos";
            //得到第三方服务器上传相关配置
            if ($uploadConfig['upload_type'] !== 'local') {
                $uploadConfig = array_merge($uploadConfig, \app\common\model\Config::getConfigData('storage', $uploadConfig['upload_type'], 'local'));
            }
            $upload = Uploadfile::instance()
                ->setUploadType($uploadConfig['upload_type'])
                ->setUploadConfig($uploadConfig)
                ->setMemberId($member_mini_app['member_id'])
                ->setFile($files)
                ->save();
            // TODO: 生成后删除源文件
            @unlink('.' . $wapCodePath);
            if ($upload['save']) {
                return $upload['file_info'];
            } else {
                return $upload['msg'];
            }
        } catch (\Exception $e) {

            return $e->getMessage();
        }
    }

    //解密小程序的加密信息
    public static function getMiniDataValue($app_id, $session, $iv, $encryptedData)
    {
        //生成小程序二维码
        $app = WechatProgram::getWechatObj($app_id);
        if (!$app) throw new Exception('微信认证失败,请确认应用已授权');
        return $app->encryptor->decryptData($session, $iv, $encryptedData);
    }


    /**
     *
     * 处理成圆图片,如果图片不是正方形就取最小边的圆半径,从左边开始剪切成圆形
     * @param string $imgpath [description]
     * @return [type]          [description]
     */
    public static function yuan_img($imgpath = './tx.jpg')
    {
        $ext = pathinfo($imgpath);
        $src_img = null;
        //TODO:2021/3/18 图片兼容调整
        try {
            $src_img = imagecreatefromjpeg($imgpath);
        } catch (\Throwable  $e) {
            $src_img = imagecreatefrompng($imgpath);
        }
//        switch ($ext['extension']??'jpg') {
//            case 'jpg':
//                $src_img = imagecreatefromjpeg($imgpath);
//                break;
//            case 'png':
//                $src_img = imagecreatefrompng($imgpath);
//                break;
//            default:
//                try{
//                    $src_img = imagecreatefromjpeg($imgpath);
//                }catch (\Throwable  $e){
//                    $src_img = imagecreatefrompng($imgpath);
//                }
//        }
        $wh = getimagesize($imgpath);
        $w = $wh[0];
        $h = $wh[1];
        $w = min($w, $h);
        $h = $w;
        $img = imagecreatetruecolor($w, $h);
        //这一句一定要有
        imagesavealpha($img, true);
        //拾取一个完全透明的颜色,最后一个参数127为全透明
        $bg = imagecolorallocatealpha($img, 255, 255, 255, 127);
        imagefill($img, 0, 0, $bg);
        $r = $w / 2; //圆半径
        $y_x = $r; //圆心X坐标
        $y_y = $r; //圆心Y坐标
        for ($x = 0; $x < $w; $x++) {
            for ($y = 0; $y < $h; $y++) {
                $rgbColor = imagecolorat($src_img, $x, $y);
                if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
                    imagesetpixel($img, $x, $y, $rgbColor);
                }
            }
        }
        return $img;
    }


    /**
     *等比例缩放函数（以保存新图片的方式实现）
     * @param string $picName 被缩放的处理图片源
     * @param string $savePath 保存路径
     * @param int $maxx 缩放后图片的最大宽度
     * @param int $maxy 缩放后图片的最大高度
     * @param string $pre 缩放后图片的前缀名
     * @return $string 返回后的图片名称（） 如a.jpg->s.jpg
     *
     **/
    public static function scaleImg($picName, $im, $maxx = 800, $maxy = 450)
    {
        $info = getimageSize($picName);//获取图片的基本信息
        $w = $info[0];//获取宽度
        $h = $info[1];//获取高度

        if ($w <= $maxx && $h <= $maxy) {
            return $picName;
        }
        //计算缩放比例
        if (($maxx / $w) > ($maxy / $h)) {
            $b = $maxy / $h;
        } else {
            $b = $maxx / $w;
        }
        //计算出缩放后的尺寸
        $nw = floor($w * $b);
        $nh = floor($h * $b);
        //创建一个新的图像源（目标图像）
        $nim = imagecreatetruecolor($nw, $nh);

        //透明背景变黑处理
        //2.上色
        $color = imagecolorallocate($nim, 255, 255, 255);
        //3.设置透明
        imagecolortransparent($nim, $color);
        imagefill($nim, 0, 0, $color);


        //执行等比缩放
        imagecopyresampled($nim, $im, 0, 0, 0, 0, $nw, $nh, $w, $h);
        //返回结果
        return $nim;
    }


    /**下载文件（nginx重定向下载）
     * @param $filepath 文件url
     * @param $type local 去本地仓库下载  alioss 去阿里云下载
     */
    public static function download($filepath, $type = 'alioss')
    {
        $url_info = parse_url($filepath);
        $filename = basename($filepath);
        $filepath = $url_info['path'];
        header("Content-Disposition: attachment; filename= {$filename}");
        header("Content-Type: application/octet-stream");
        header("X-Accel-Redirect: /{$type}/{$filepath}");
        header("X-Accel-Buffering: yes");
        header("X-Accel-Limit-Rate :102400"); //速度限制 Byte/s
        //header("Accept-Ranges: none");//单线程 限制多线程
    }


    /** 给创建表Sql增加通用表设置
     * @param $table_create_info
     */
    public static function setTableSqlCommonType($create_table_sql)
    {
        $table_set_str = strstr($create_table_sql, 'ENGINE='); //返回表设置字符串
        //建表sql去掉表设置
        $create_table_sql = str_replace($table_set_str, "", $create_table_sql);
        //得到表注释
        $comment_str = strstr($table_set_str, 'COMMENT=');
        if (!$comment_str) $comment_str = '';
        //去掉表设置中的默认设置
        $default_str = strstr($table_set_str, 'DEFAULT');
        $table_set_str = str_replace($default_str, "", $table_set_str);
        //设置表的默认字符集
        $charset = "CHARSET=utf8mb4";
        //设置表的默认校对规则
        $collate = "COLLATE utf8mb4_unicode_ci";
        //组装sql
        return "{$create_table_sql}{$table_set_str} DEFAULT {$charset} {$collate} {$comment_str}";
    }
}